#include "camera.hpp"
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>

using namespace std::chrono_literals;

namespace libcamcv {

Camera::Camera()
    : cameraManager_(nullptr), camera_(nullptr), stream_(nullptr),
      running_(false) {}

Camera::~Camera() {
  stop();
  cleanup();
}

bool Camera::init(int width, int height, libcamera::PixelFormat format) {
  // 创建相机管理器
  cameraManager_ = std::make_unique<libcamera::CameraManager>();
  if (cameraManager_->start()) {
    std::cerr << "Failed to start camera manager" << std::endl;
    return false;
  }

  // 获取相机列表
  const auto &cameras = cameraManager_->cameras();
  if (cameras.empty()) {
    std::cerr << "No cameras available" << std::endl;
    return false;
  }

  // 获取第一个相机
  camera_ = cameras.front();
  if (camera_->acquire()) {
    std::cerr << "Failed to acquire camera" << std::endl;
    return false;
  }

  // 生成配置
  config_ = camera_->generateConfiguration({libcamera::StreamRole::Viewfinder});
  if (!config_) {
    std::cerr << "Failed to generate configuration" << std::endl;
    return false;
  }

  // 配置流
  auto &streamConfig = config_->at(0);
  streamConfig.size = libcamera::Size(width, height);
  streamConfig.pixelFormat = format;

  // 验证配置
  if (config_->validate() == libcamera::CameraConfiguration::Invalid) {
    std::cerr << "Configuration invalid" << std::endl;
    return false;
  }

  // 配置相机
  if (camera_->configure(config_.get())) {
    std::cerr << "Failed to configure camera" << std::endl;
    return false;
  }

  stream_ = streamConfig.stream();
  return true;
}

bool Camera::allocateBuffers() {
  // 分配帧缓冲区
  allocator_ = std::make_unique<libcamera::FrameBufferAllocator>(camera_);
  if (allocator_->allocate(stream_) < 0) {
    std::cerr << "Failed to allocate buffers" << std::endl;
    return false;
  }

  // 获取分配的缓冲区
  const auto &buffers = allocator_->buffers(stream_);
  if (buffers.empty()) {
    std::cerr << "No buffers allocated" << std::endl;
    return false;
  }

  // 存储缓冲区指针
  bufferPtrs_.clear();
  for (const auto &buffer : buffers) {
    bufferPtrs_.push_back(buffer.get());
  }

  return true;
}

bool Camera::createRequests() {
  // 创建请求并关联缓冲区
  requests_.clear();
  for (unsigned int i = 0; i < bufferPtrs_.size(); i++) {
    auto request = camera_->createRequest(i);
    if (!request) {
      std::cerr << "Failed to create request" << std::endl;
      return false;
    }

    if (request->addBuffer(stream_, bufferPtrs_[i])) {
      std::cerr << "Failed to add buffer to request" << std::endl;
      return false;
    }

    requests_.push_back(std::move(request));
  }

  return true;
}

void Camera::setFrameCallback(const FrameCallback &callback) {
  std::lock_guard<std::mutex> lock(frameMutex_);
  frameCallback_ = callback;
}

bool Camera::start() {
  if (running_)
    return true;

  // 分配缓冲区
  if (!allocateBuffers())
    return false;

  // 创建请求
  if (!createRequests())
    return false;

  // 启动相机
  if (camera_->start()) {
    std::cerr << "Failed to start camera" << std::endl;
    return false;
  }

  // 提交所有初始请求
  for (auto &request : requests_) {
    if (camera_->queueRequest(request.get())) {
      std::cerr << "Failed to queue initial request" << std::endl;
      camera_->stop();
      return false;
    }
  }

  // 启动捕获线程
  running_ = true;
  captureThread_ = std::thread(&Camera::captureLoop, this);
  return true;
}

void Camera::stop() {
  if (!running_)
    return;

  running_ = false;
  if (captureThread_.joinable())
    captureThread_.join();

  if (camera_)
    camera_->stop();
}

void Camera::captureLoop() {
  while (running_) {
    // 等待请求完成
    libcamera::Request *completedRequest = nullptr;
    for (auto &request : requests_) {
      if (request->status() == libcamera::Request::RequestComplete) {
        completedRequest = request.get();
        break;
      }
    }

    // 如果没有完成的请求，等待一段时间
    if (!completedRequest) {
      std::this_thread::sleep_for(10ms);
      continue;
    }

    // 处理请求
    processRequest(completedRequest);

    // 重新准备请求
    completedRequest->reuse();

    // 重新添加缓冲区
    unsigned int index = completedRequest->cookie();
    if (index < bufferPtrs_.size()) {
      if (completedRequest->addBuffer(stream_, bufferPtrs_[index])) {
        std::cerr << "Failed to add buffer to reused request" << std::endl;
      }

      // 重新提交请求
      if (camera_->queueRequest(completedRequest)) {
        std::cerr << "Failed to re-queue request" << std::endl;
      }
    } else {
      std::cerr << "Invalid cookie index: " << index << std::endl;
    }
  }
}

void Camera::processRequest(libcamera::Request *request) {
  // 获取缓冲区
  libcamera::FrameBuffer *buffer = request->buffers().at(stream_);

  // 映射内存
  const libcamera::FrameBuffer::Plane &plane = buffer->planes().front();
  void *data =
      mmap(nullptr, plane.length, PROT_READ, MAP_SHARED, plane.fd.get(), 0);
  if (data == MAP_FAILED) {
    std::cerr << "Failed to mmap buffer" << std::endl;
    return;
  }

  // 创建OpenCV图像
  int width = config_->at(0).size.width;
  int height = config_->at(0).size.height;

  // 直接创建BGR图像（XRGB8888实际上是BGRA格式）
  cv::Mat bgra(height, width, CV_8UC4, data);

  // 转换为BGR格式（去除alpha通道）
  cv::Mat frame;
  cv::cvtColor(bgra, frame, cv::COLOR_BGRA2BGR);

  // 取消映射
  munmap(data, plane.length);

  // 调用回调函数
  if (!frame.empty() && frameCallback_) {
    std::lock_guard<std::mutex> lock(frameMutex_);
    frameCallback_(frame);
  }
}

void Camera::cleanup() {
  if (camera_) {
    camera_->release();
    camera_.reset();
  }

  if (cameraManager_) {
    cameraManager_->stop();
    cameraManager_.reset();
  }
}

std::string Camera::getCameraId() const {
  if (camera_)
    return camera_->id();
  return "";
}

bool Camera::isRunning() const { return running_; }

} // namespace libcamcv